﻿using System;
using System.Web.Mvc;
using Tools.Common.Reflection;
using Web.App.Infrastructure.ApplicationMessages.Contracts;
using Web.App.Infrastructure.ApplicationMessages.Implementation;
using Web.App.Infrastructure.Extensions;
using Web.App.Infrastructure.Interface;
using Web.App.Infrastructure.Interface.Contracts;
using Web.App.Infrastructure.Localization.Contract;
using Webshop20.Application;
using Webshop20.Application.Operations.Messages;
using Webshop20.Application.Operations.Services;
using Webshop20.Application.Queries.Messages;
using Webshop20.Application.Queries.Services;
using Webshop20.Presentation;
using Webshop20.Values;

namespace Webshop20.Interface.MVC.Controllers
{
    /// <summary>
    /// The the user wants to log in. If he
    /// enters the correct credentials the system
    /// will do the login and redirect him to the
    /// landig page (with a welcome message)
    /// If he ist not yet registered he can do so 
    /// (starts a sub use case register).
    /// If he enters false credentials an error
    /// message will be shown.
    /// If he has forgotten his password he can
    /// order a new one.
    /// </summary>
    public class LoginController : ControllerBase
    {
        private readonly ICookieFactory cookieFactory;
        private readonly ILoginService loginService;
        private readonly INewPasswordService newPasswordService;
        private IMergeCartsService mergeCartsService; 


        public LoginController(
                                ILoginService loginService,
                                ICookieFactory cookieFactory, 
                                ILocalisationService localisationService,
                                INewPasswordService newPasswordService, 
                                IMergeCartsService mergeCartsService)
            : base(localisationService)
        {
            this.cookieFactory = cookieFactory;
            this.mergeCartsService = mergeCartsService;
            this.newPasswordService = newPasswordService;
            this.loginService = loginService;
        }

        [AcceptVerbs(HttpVerbs.Get)]
        public ActionResult Index(ControllerRedirect redirect)
        {
           return View(new LoginForm(string.Empty, string.Empty, redirect.ControllerName ?? "Home", redirect.ControllerAction ?? "Index"));
        }

        [ActionName("Index")]
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Authenticate(LoginRequest request, ControllerRedirect redirect)
        {
            var loginResponse =
                loginService.Handle(request) as LoginResponse;

            if (loginResponse.IsAuthenticated_)
            {
                AddAuthenticationCookie(loginResponse.AccountId.ToString());

                if (request.AnonymousVisitorId.Exists())
                {
                    mergeCartsService.Handle(new MergeCartsRequest(request.AnonymousVisitorId, loginResponse.AccountId));
                    RemoveCookie(ReflectAbout<RequestMessageBase>.GetProperty(x=>x.AnonymousVisitorId).Name);
                }

                return RedirectToAction(redirect.ControllerAction, redirect.ControllerName, redirect.ActionParameters);
            }

            AddErrorMessagesToViewDataModelState(loginResponse.DomainMessage);
            return View();
        }


        private void AddAuthenticationCookie(string userId)
        {
            ControllerContext
                .HttpContext
                .Response
                .Cookies
                .Add(cookieFactory.CreateAuthenticationCookie(userId, false));
        }


        public ActionResult Register()
        {
            return RedirectToAction("Index", "Register");
        }

        [AcceptVerbs("Get")]
        public ActionResult NewPassword()
        {
            return View();
        }

        [AcceptVerbs("POST")]
        [ActionName("NewPassword")]
        public ActionResult SendNewPassword(string eMailAdress, string controlQuestion, string controlAnswer)
        {
            var result =
                newPasswordService.Handle(new NewPasswordRequest(eMailAdress, controlQuestion, controlAnswer)) as
                NewPasswordResponse;

            if (result.DomainMessage != null)
            {
                AddErrorMessagesToViewDataModelState(result.DomainMessage);
                return View(VIEWS.LOGIN.NEW_PASSWORD);
            }

            return View(VIEWS.LOGIN.PASSWORD_SUCCESS);
        }


    }
}